home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Sample Controls / BDiamond / Colors.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-20  |  9.5 KB  |  278 lines  |  [TEXT/CWIE]

  1.  
  2. #include "Colors.h"
  3. #include "BDAssert.h"
  4. #include <algobase.h>
  5. #include <stdio.h>
  6.  
  7. ///////////////////////////////////////////////////////////////////////////////
  8. //
  9. //  Initialize colors
  10. //
  11.  
  12. // Mac Standard Colors
  13. const RGBColor RGB_WHITE        = { 0xFFFF, 0xFFFF, 0xFFFF };
  14. const RGBColor RGB_BLACK        = { 0x0000, 0x0000, 0x0000 };
  15. const RGBColor RGB_YELLOW        = { 0xFC00, 0xF37D, 0x052F };
  16. const RGBColor RGB_MAGENTA         = { 0xF2D7, 0x0856, 0x84EC };
  17. const RGBColor RGB_RED             = { 0xDD6B, 0x08C2, 0x06A2 };
  18. const RGBColor RGB_CYAN         = { 0x0241, 0xAB54, 0xEAFF };
  19. const RGBColor RGB_GREEN         = { 0x0000, 0x8000, 0x11B0 };
  20. const RGBColor RGB_BLUE         = { 0x0000, 0x0000, 0xD400 };
  21.  
  22. // Mac non-standard colors
  23. const RGBColor RGB_GRAY         = { 0x8080, 0x8080, 0x8080 }; // same as COLORREF_GRAY
  24. const RGBColor RGB_LTGRAY         = { 0xC0C0, 0xC0C0, 0xC0C0 }; // same as COLORREF_LTGRAY
  25. const RGBColor RGB_BROWN         = { 0x0000, 0x8080, 0x8080 }; // same as COLORREF_BROWN
  26.  
  27. // Windows standards, taken from Intrinsic tickctl.h, OLE_COLORs
  28. const RGBColor COLORREF_RED            = { 0x0000, 0x0000, 0x8080 };
  29. const RGBColor COLORREF_GREEN        = { 0x0000, 0x8080, 0x0000 };
  30. const RGBColor COLORREF_BLUE        = { 0x8080, 0x0000, 0x0000 };
  31. const RGBColor COLORREF_MAGENTA        = { 0x8080, 0x0000, 0x8080 };
  32. const RGBColor COLORREF_CYAN        = { 0x8080, 0x8080, 0x0000 };
  33. const RGBColor COLORREF_BLACK        = { 0x0000, 0x0000, 0x0000 };
  34. const RGBColor COLORREF_YELLOW        = { 0x0000, 0xFFFF, 0xFFFF };
  35. const RGBColor COLORREF_WHITE        = { 0xFFFF, 0xFFFF, 0xFFFF };
  36. // (ones that don't have a direct match on Mac)
  37. const RGBColor COLORREF_LTRED        = { 0x0000, 0x0000, 0xFFFF };
  38. const RGBColor COLORREF_LTGREEN        = { 0x0000, 0xFFFF, 0x0000 };
  39. const RGBColor COLORREF_LTBLUE        = { 0xFFFF, 0x0000, 0x0000 };
  40. const RGBColor COLORREF_LTMAGENTA    = { 0xFFFF, 0x0000, 0xFFFF };
  41. const RGBColor COLORREF_LTCYAN        = { 0xFFFF, 0xFFFF, 0x0000 };
  42. // (bonus colors -- ones that have no match at all on Mac)
  43. const RGBColor COLORREF_GRAY        = { 0x8080, 0x8080, 0x8080 };
  44. const RGBColor COLORREF_LTGRAY        = { 0xC0C0, 0xC0C0, 0xC0C0 };
  45. const RGBColor COLORREF_BROWN        = { 0x0000, 0x8080, 0x8080 };
  46.  
  47. const short SIZEOF_MATCHING_COLORS = 8; // update this if you add to the array!
  48. const RGBColor * MATCHING_COLORS[] =
  49. {    
  50.     &COLORREF_RED,            // <-- same as COLORREF_LTRED (matching index!)
  51.     &COLORREF_GREEN,        // <-- same as COLORREF_LTGREEN (matching index!)
  52.     &COLORREF_BLUE,            // <-- same as COLORREF_LTBLUE (matching index!)
  53.     &COLORREF_MAGENTA,        // <-- same as COLORREF_LTMAGENTA (matching index!)
  54.     &COLORREF_CYAN,            // <-- same as COLORREF_LTCYAN (matching index!)
  55.     &COLORREF_BLACK,
  56.     &COLORREF_YELLOW,
  57.     &COLORREF_WHITE
  58. };
  59.  
  60. const short SIZEOF_CLOSE_COLORS = 5; // update this if you add to the array!
  61. const RGBColor * CLOSE_COLORS[] = 
  62. {    
  63.     &COLORREF_LTRED,        // <-- treat as COLORREF_RED (matching index!)
  64.     &COLORREF_LTGREEN,        // <-- treat as COLORREF_GREEN (matching index!)
  65.     &COLORREF_LTBLUE,        // <-- treat as COLORREF_BLUE (matching index!)
  66.     &COLORREF_LTMAGENTA,    // <-- treat as COLORREF_MAGENTA (matching index!)
  67.     &COLORREF_LTCYAN,        // <-- treat as COLORREF_CYAN (matching index!)
  68. };
  69.  
  70. const short SIZEOF_BONUS_COLORS = 3; // update this if you add to the array!
  71. const RGBColor * BONUS_COLORS[] = 
  72. {
  73.     &COLORREF_GRAY,
  74.     &COLORREF_LTGRAY,
  75.     &COLORREF_BROWN
  76. };
  77.  
  78. ///////////////////////////////////////////////////////////////////////////////
  79. //
  80. //  MapColorRefToRGBColor
  81. //
  82.  
  83. void MapColorRefToRGBColor(const COLORREF * desiredColorRef, RGBColor * desiredRGBColor, Boolean useColorMatching)
  84. {
  85.     // A COLORREF in Windows is a triplet of bytes.  An RGBColor is
  86.     // a triplet of shorts (two bytes).  The input for the color is in the 
  87.     // format #00bbggrr (hex), indicating a COLORREF (one-byte triplet), not
  88.     // an RGBColor (two-byte triplet).  One way to translate would be to simply map
  89.     // a one-byte range into a two-byte range (as below).  This would not map colors
  90.     // very well.  But we'll start with that.
  91.  
  92.     // Range mapping:
  93.     desiredRGBColor->red   = desiredColorRef->red   * CONVERSION;
  94.     desiredRGBColor->green = desiredColorRef->green * CONVERSION;
  95.     desiredRGBColor->blue  = desiredColorRef->blue  * CONVERSION;
  96.  
  97.     // What we'll do now is try to match the standard nearest system color, 
  98.     // making the assumption that most people will be using something pretty
  99.     // standard for the stock ticker.  We'll even add some smarts for special
  100.     // cases like primary colors red, green, and blue (note that, for instance, 
  101.     // a COLORREF of "red" is {0x00, 0x00, 0xff} -- not much like RGB_RED).
  102.         
  103.     if ( useColorMatching )
  104.     {
  105.         // Find the closest color match (crude algorithm)
  106.         
  107.         unsigned short delta = 0;
  108.         short i = 0;
  109.                 
  110.         // first, search in the set of colors defined on windows and mac
  111.         unsigned long matchingDelta;
  112.         short matchingIndex = -1;
  113.         MatchColor(desiredRGBColor, MATCHING_COLORS, SIZEOF_MATCHING_COLORS, matchingDelta, matchingIndex);
  114.         
  115.         // next, search the set of colors that have close, but not exact
  116.         // matches on the mac.
  117.         unsigned long closeDelta;
  118.         short closeIndex = -1;
  119.         MatchColor(desiredRGBColor, CLOSE_COLORS, SIZEOF_CLOSE_COLORS, closeDelta, closeIndex);
  120.         
  121.         // finally, search the set of colors that have no real standard match
  122.         // on the mac
  123.         unsigned long bonusDelta;
  124.         short bonusIndex = -1;
  125.         MatchColor(desiredRGBColor, BONUS_COLORS, SIZEOF_BONUS_COLORS, bonusDelta, bonusIndex);
  126.         
  127.         // if the closest match we've found is in the "matching" list, do the 
  128.         // translation.  If it's in the "close" list, use the closest match
  129.         // in the "matching" list, by using the corresponding array index.  
  130.         // If it's in the "bonus" list, invent our own.
  131.         
  132.         if ( bonusDelta == MIN3(matchingDelta, closeDelta, bonusDelta) )
  133.             SET_COLOR(*desiredRGBColor, BONUS_COLORS[bonusIndex]) // ;
  134.         else
  135.         {
  136.             short theIndex = closeIndex;
  137.             if ( matchingDelta == MIN3(matchingDelta, closeDelta, bonusDelta) )
  138.                 theIndex = matchingIndex;
  139.             SET_COLOR(*desiredRGBColor, MATCHING_COLORS[theIndex]) // ;
  140.         }
  141.     }
  142. }
  143.  
  144. ///////////////////////////////////////////////////////////////////////////////
  145. //
  146. //  MatchColor
  147. //
  148.                 
  149. void MatchColor (
  150.     const RGBColor * targetColor, 
  151.     const RGBColor ** colorPtrArray, 
  152.     short arraySize, 
  153.     unsigned long & delta, 
  154.     short & index )
  155. {
  156.     delta = 0xFFFFFFFF;
  157.     index = -1;
  158.  
  159.     unsigned long newDelta;
  160.  
  161.     for ( short i = 0; i < arraySize; i++ )
  162.     {
  163.         newDelta = RGBDELTA((colorPtrArray[i]), targetColor);
  164.         
  165.         if ( newDelta <= delta )
  166.         {
  167.             delta = newDelta;
  168.             index = i;
  169.         }
  170.     }
  171. }
  172.  
  173.  
  174. ///////////////////////////////////////////////////////////////////////////////
  175. //
  176. //  RGBColorsEQ
  177. //
  178. //    returns true if the input colors are identical
  179. //
  180.  
  181. Boolean RGBColorsEQ ( const RGBColor & color1, const RGBColor & color2 )
  182. {
  183.     Boolean colorsAreEqual = true;
  184.     
  185.     if (     color1.red != color2.red ||
  186.             color1.green != color2.green ||
  187.             color1.blue != color2.blue )
  188.         colorsAreEqual = false;
  189.     
  190.     return colorsAreEqual;
  191. }
  192.         
  193.  
  194. ///////////////////////////////////////////////////////////////////////////////
  195. //
  196. //  RGBColorsPERCENT
  197. //
  198. //    color        the color we want a percentage of
  199. //    percent        the percent of a color expressed as a value from 0.0 to 1.0
  200. //    
  201. //    returns a weighted value of the RGBColor passed in
  202. //
  203.  
  204. RGBColor RGBColorsPERCENT(const RGBColor color, const double percent)
  205. {
  206.     // first check out the percent to make sure that it is in range:
  207. #ifdef _DEBUG
  208.         assert(percent <= 1.0 && percent >= 0.0);
  209. #endif
  210.     RGBColor weightedColor;
  211.     
  212.     weightedColor.red = color.red * percent;
  213.     weightedColor.green = color.green * percent;
  214.     weightedColor.blue = color.blue * percent;
  215.     
  216.     return weightedColor;
  217. }
  218.         
  219.  
  220. ///////////////////////////////////////////////////////////////////////////////
  221. //
  222. //  RGBColorsPLUS
  223. //
  224. //    color1        the first color we want to sum
  225. //    color2        the second color we want to sum
  226. //    returns the sum of two colors
  227. //
  228.  
  229. RGBColor RGBColorsPLUS(const RGBColor color1, const RGBColor color2)
  230. {
  231.     RGBColor additiveColor;
  232.     
  233.     // add each component and make sure it does not exceed the max value
  234.     additiveColor.red = min(MAX_USHORT, color1.red + color2.red);
  235.     additiveColor.green = min(MAX_USHORT, color1.green + color2.green);
  236.     additiveColor.blue = min(MAX_USHORT, color1.blue + color2.blue);
  237.     
  238.     return additiveColor;
  239. }
  240.         
  241.  
  242. ///////////////////////////////////////////////////////////////////////////////
  243. //
  244. //  RGBColorsInterpolate
  245. //
  246. //    color1        the color we want to subtract from
  247. //    color2        the color we want to subtract
  248. //    returns the sum of two colors
  249. //
  250.  
  251. RGBColor RGBColorsInterpolate(const RGBColor color1, const RGBColor color2, double percent)
  252. {
  253.     // first check out the percent to make sure that it is in range:
  254. #ifdef _DEBUG
  255.         assert(percent <= 1.0 && percent >= 0.0);
  256. #endif
  257.     RGBColor interpolatedColor;
  258.     // color1 is our base to interpolate from so we compute the distance between pairs
  259.     // and then multiply by the weight -- that value is then added back to the base
  260.     // to give us the 'final' color. Note that this is done with signed values so it
  261.     // is important which order we subtract in.
  262.     
  263.     // compute the weighted amount of each component (signed value)
  264.     short redOffset = (short)(percent * (double)(color1.red - color2.red));
  265.     short greenOffset = (short)(percent * (double)(color1.green - color2.green));
  266.     short blueOffset = (short)(percent * (double)(color1.blue - color2.blue));
  267.     
  268.     // We always subtract the 2nd color from the 1st and then multiple by something <= 1.0
  269.     // so we can be sure that when we add this back to the 1st coord that it will not
  270.     // overflow a signed short.
  271.     interpolatedColor.red = (unsigned short)((short)(color1.red) - redOffset);
  272.     interpolatedColor.green = (unsigned short)((short)(color1.green) - greenOffset);
  273.     interpolatedColor.blue = (unsigned short)((short)(color1.blue) - blueOffset);
  274.     
  275.     return interpolatedColor;
  276. }
  277.         
  278. //end-of-file